﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace gnuProload_ex01
{
    public partial class mainWindow : Form
    {
        string RxString = "";
        string hex_file_str = "";   
        string single_string_of_code = "";
        int total_bytes = 0;

        public mainWindow()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            textBox1.ReadOnly = true;
            textBox2.ReadOnly = true;
            textBox1.BackColor = Color.White;
            textBox1.TabStop = false;
           
            if (!serialPort1.IsOpen)
            {
                try
                {
                    serialPort1.Open();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);

                }
            }
            else 
            {

                MessageBox.Show("Serial Port is already Open","Error");
                this.Close();
            }
        }

        private void mainWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                serialPort1.Close();
            
            }
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
           // RxString = serialPort1.ReadExisting();
            //this.Invoke(new EventHandler(DisplayText));
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                byte[] cmd = new byte[5];
                char[] invalid = System.IO.Path.GetInvalidFileNameChars();

                cmd[0] = 0x0D;  //initialize ID
                cmd[1] = 0x67;  // Query ID CMD
                cmd[2] = 0x65;  // Erase Command 
                cmd[3] = 0x70;  // Get Summary 
                cmd[4] = 0x73;  // Write Size 

                String test_str = "0D";
                cmd[0] = Convert.ToByte(test_str, 16);

                //initialize
                serialPort1.Write(cmd, 0, 1);
                RxString = serialPort1.ReadTo(">");
                var newstr = new String(RxString.Where(c => !invalid.Contains(c)).ToArray());
                textBox1.AppendText(newstr);
                textBox1.AppendText(Environment.NewLine);

                //Query ID
                serialPort1.Write(cmd, 1, 1);
                RxString = serialPort1.ReadTo(">");
                newstr = new String(RxString.Where(c => !invalid.Contains(c)).ToArray());
                textBox1.AppendText(newstr);
                textBox1.AppendText(Environment.NewLine);

                //Erase Command 
                serialPort1.Write(cmd, 2, 1);
                RxString = serialPort1.ReadTo(">");
                newstr = new String(RxString.Where(c => !invalid.Contains(c)).ToArray());
                textBox1.AppendText(newstr);
                textBox1.AppendText(Environment.NewLine);


                //Get summary 
                serialPort1.Write(cmd, 3, 1);
                RxString = serialPort1.ReadTo(">");
                newstr = new String(RxString.Where(c => !invalid.Contains(c)).ToArray());
                textBox1.AppendText(newstr);
                textBox1.AppendText(Environment.NewLine);

                /*
                 //Get write size
                 serialPort1.Write(cmd, 4, 1);
                 RxString = serialPort1.ReadTo(Convert.ToChar(0x11).ToString());
                 //RxString = serialPort1.ReadLine();
                 newstr = new String(RxString.Where(c => !invalid.Contains(c)).ToArray());
                 textBox1.AppendText(newstr);
                 textBox1.AppendText(Environment.NewLine);

                 */

            }
            catch (Exception ex)
            {

                textBox1.AppendText(Environment.NewLine + ex.Message);
            
            }




        }

        private void DisplayText(object sender, EventArgs e)
        {
            textBox1.AppendText(RxString);
            

        }

        private void button2_Click(object sender, EventArgs e)
        {
            OpenFileDialog op = new OpenFileDialog();
            op.Filter = "Intel Hex Files (*.hex)|*.hex";
            if (op.ShowDialog() == DialogResult.OK)
            {
                textBox2.Text = op.FileName;

                try
                {
                    //FileStream fs = File.OpenRead(op.FileName);
                    byte[] otherData = File.ReadAllBytes(op.FileName);
                    hex_file_str = System.Text.Encoding.Default.GetString(otherData);
                    string[] parts = hex_file_str.Split(new string[]{"\r\n"},StringSplitOptions.RemoveEmptyEntries);

                    single_string_of_code = "";
                    string count="", address="", type="";
                 //   max_count = 0; max_address = 0;
                    total_bytes = 0;
                  
                    for (int i = 0; i < parts.Length; i++)
                    {
                        if (parts[i][0] == ':')
                        {

                            count = parts[i].Substring(1, 2);
                            address = parts[i].Substring(3, 4);
                            type = parts[i].Substring(7, 2);
                            int cnt = Convert.ToInt16(count,16);
                            int add = Convert.ToInt16(address, 16);
                            if (cnt > 0)
                            {
                                total_bytes = cnt + add;
                            }
                            
                            

                            single_string_of_code += parts[i].Substring(9, cnt*2);
                            //MessageBox.Show(single_string_of_code, ((parts[i].Length)/2).ToString());
                        }
                        else 
                          {
                              MessageBox.Show("Not a valid Intel(r) Hex file ", "Invalid file", MessageBoxButtons.OK, MessageBoxIcon.Error);
                              break;
                        
                          }
                    }


                    textBox1.AppendText(Environment.NewLine + "File Loaded, total_bytes=" + (single_string_of_code.Length / 2).ToString()+Environment.NewLine);

                //    MessageBox.Show(single_string_of_code + ", L=" + single_string_of_code.Length, "A=" + max_address.ToString() + ", C=" + max_count.ToString() + ", Total=" + (total_bytes).ToString());

                    

                }
                catch(Exception ex)
                {
                MessageBox.Show(ex.Message);
                hex_file_str = "";
                }
                


            }
            else 
            {
                MessageBox.Show("operation aborted");
            
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            try
            {
                byte[] cmd = new byte[6];
                String newstr = "";
                char[] invalid = System.IO.Path.GetInvalidFileNameChars();

                cmd[0] = 0x0D;  //initialize ID
                cmd[1] = 0x67;  // Query ID CMD
                cmd[2] = 0x65;  // Erase Command 
                cmd[3] = 0x70;  // Get Summary 
                cmd[4] = 0x73;  // Write Size 
                cmd[5] = 0x77;  // COMMENCE_PROGRAM

                if (single_string_of_code.Length > 0)
                {
                    textBox1.AppendText(System.Environment.NewLine + "Burning Microcontroller with " + single_string_of_code.Length / 2);
                    //Get write size
                    serialPort1.Write(cmd, 4, 1);
                    RxString = serialPort1.ReadTo(Convert.ToChar(0x11).ToString());
                    //RxString = serialPort1.ReadLine();
                    newstr = new String(RxString.Where(c => !invalid.Contains(c)).ToArray());
                    textBox1.AppendText(newstr);
                    textBox1.AppendText(Environment.NewLine);
                    total_bytes = single_string_of_code.Length / 2;
                    int code_length = single_string_of_code.Length/2;
                    int thou = 0, hund = 0, tens = 0, units = 0;
                    int f_size = code_length;

                    thou = f_size / 1000;
                    f_size %= 1000;

                    hund = f_size / 100;
                    f_size %= 100;

                    tens = f_size / 10;
                    f_size %= 10;

                    units = f_size;



                    serialPort1.Write(thou.ToString());
                    RxString = serialPort1.ReadTo(Convert.ToChar(0x11).ToString());
                   

                    serialPort1.Write(hund.ToString());
                    RxString = serialPort1.ReadTo(Convert.ToChar(0x11).ToString());
                   
                    serialPort1.Write(tens.ToString());
                    RxString = serialPort1.ReadTo(Convert.ToChar(0x11).ToString());
                   


                    serialPort1.Write(units.ToString());
                    serialPort1.Write(Convert.ToChar(0x0A).ToString());

                    RxString = serialPort1.ReadTo(">");
                    newstr = new String(RxString.Where(c => !invalid.Contains(c)).ToArray());
                    textBox1.AppendText(newstr);
                    textBox1.AppendText(Environment.NewLine+"Writing to micro...");



                    //Commence Programe 
                    serialPort1.Write(cmd, 5, 1);
                   
                    RxString = serialPort1.ReadTo(Convert.ToChar(0x11).ToString());
                    newstr = new String(RxString.Where(c => !invalid.Contains(c)).ToArray());
                    textBox1.AppendText(newstr);
                    textBox1.AppendText(Environment.NewLine);
                   


                    byte[] code_in_bytes_form = new byte[total_bytes];

                    for (int j = 0, i = 0; i < single_string_of_code.Length; i += 2, j++)
                    {
                        code_in_bytes_form[j] = Convert.ToByte(single_string_of_code.Substring(i, 2), 16);



                    }


                    for (int k = 0; k < code_length; k++)
                    {

                        serialPort1.Write(code_in_bytes_form, k, 1);

                        if (k < code_length - 1)
                        {
                            /* we should NOT wait for ack for the last byte */
                            RxString = serialPort1.ReadTo(Convert.ToChar(0x11).ToString());
                            
                            
                        }


                    }



                    textBox1.AppendText("Programming complete" + Environment.NewLine);








                }
                else
                {
                    MessageBox.Show("Please load hex file first ", "Error: No Hex", MessageBoxButtons.OK, MessageBoxIcon.Error);

                }
            }
            catch (Exception ex)
            {
                textBox1.AppendText(Environment.NewLine + ex.Message);
            
            }
                
        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {

        }

       //=======================================================================

        
    }
}
